package cn.sciento.boot.data.change.utils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.collections4.CollectionUtils;
import cn.sciento.boot.data.change.parse.InsertDataParser;
import cn.sciento.core.util.FieldNameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FieldUtil {
  private static final Logger logger = LoggerFactory.getLogger(InsertDataParser.class);
  
  public static Map<String, Object> underlineToCamel(Map<String, Object> objectMap) {
    Map<String, Object> resultMap = new HashMap<>(2);
    Set<Map.Entry<String, Object>> entries = objectMap.entrySet();
    for (Map.Entry<String, Object> set : entries)
      resultMap.put(FieldNameUtils.underline2Camel(set.getKey(), true), set.getValue()); 
    return resultMap;
  }
  
  public static List<Map<String, Object>> underlineToCamel(List<Map<String, Object>> list) {
    List<Map<String, Object>> resultList = new ArrayList<>();
    if (CollectionUtils.isEmpty(list))
      return resultList; 
    list.forEach(map -> resultList.add(underlineToCamel(map)));
    return resultList;
  }
  
  public static Map<String, Object> objectToUnderlineMap(Object parameter) {
    Map<String, Object> result = new HashMap<>(1);
    if (parameter != null) {
      BeanMap beanMap = new BeanMap(parameter);
      for (Object key : beanMap.keySet())
        result.put(FieldNameUtils.camel2Underline(key.toString(), false), beanMap.get(key)); 
    } 
    return result;
  }
  
  public static Map<String, Object> objectToMap(Object parameter) {
    Map<String, Object> result = new HashMap<>(1);
    if (parameter != null) {
      BeanMap beanMap = new BeanMap(parameter);
      for (Object key : beanMap.keySet())
        result.put(key.toString(), beanMap.get(key)); 
    } 
    return result;
  }
  
  public static Map<String, Object> camelToUnderline(Map<String, Object> objectMap) {
    Map<String, Object> resultMap = new HashMap<>(2);
    Set<Map.Entry<String, Object>> entries = objectMap.entrySet();
    for (Map.Entry<String, Object> set : entries)
      resultMap.put(FieldNameUtils.camel2Underline(set.getKey(), false), set.getValue()); 
    return resultMap;
  }
  
  public static <T> void changeField(T object, Object targetValue, String property) {
    if (object == null)
      return; 
    List<Field> fields = Arrays.asList(object.getClass().getDeclaredFields());
    Field targetField = fields.stream().filter(item -> property.equals(item.getName())).findFirst().orElse(null);
    if (targetField == null)
      return; 
    try {
      targetField.setAccessible(true);
      targetField.set(object, targetValue);
    } catch (IllegalAccessException e) {
      logger.error("change field with error", e);
    } 
  }
  
  public static Object getField(Object source, String property) {
    if (source == null)
      return null; 
    List<Field> fields = Arrays.asList(source.getClass().getDeclaredFields());
    Field targetField = fields.stream().filter(item -> property.equals(item.getName())).findFirst().orElse(null);
    if (targetField == null)
      return null; 
    targetField.setAccessible(true);
    try {
      return targetField.get(source);
    } catch (IllegalAccessException e) {
      logger.error("get field with error", e);
      return null;
    } 
  }
  
  public static Boolean isBasicType(Object parameter) {
    Class<?> className = parameter.getClass();
    if (className.equals(Integer.class) || className.equals(Byte.class) || className.equals(Long.class) || className
      .equals(Double.class) || className.equals(Float.class) || className
      .equals(Character.class) || className.equals(Short.class) || className
      .equals(Boolean.class) || className.equals(String.class))
      return Boolean.valueOf(true); 
    return Boolean.valueOf(false);
  }
}
